/*
 * Copyright 2005-2016 sxhuayuan.com. All rights reserved.
 */
package com.sxhuayuan.parking.compenent.shiro.realm;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.sxhuayuan.parking.entity.Salesman;
import com.sxhuayuan.parking.service.SalesmanService;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import com.sxhuayuan.parking.compenent.domain.Setting;
import com.sxhuayuan.parking.compenent.domain.Setting.AccountLockType;
import com.sxhuayuan.parking.compenent.domain.Setting.CaptchaType;
import com.sxhuayuan.parking.compenent.shiro.AccountType;
import com.sxhuayuan.parking.compenent.shiro.AuthenticationToken;
import com.sxhuayuan.parking.compenent.shiro.Principal;
import com.sxhuayuan.parking.entity.Admin;
import com.sxhuayuan.parking.service.AdminService;
import com.sxhuayuan.parking.service.CaptchaService;
import com.sxhuayuan.parking.utils.SettingUtils;

/**
 * 业务员权限认证
 */
@Component("salesmanAuthenticationRealm")
public class SalesmanAuthenticationRealm extends AuthorizingRealm {

	@Resource(name = "captchaServiceImpl")
	private CaptchaService captchaService;
	@Resource(name = "salesmanServiceImpl")
	private SalesmanService service;

	@Override
	public String getName() {
		return "salesman";
	}

	@Override
	public boolean supports(org.apache.shiro.authc.AuthenticationToken token) {
		return token instanceof AuthenticationToken;
	}

	/**
	 * 获取认证信息(登录验证)
	 *
	 * @param token
	 *            令牌
	 *
	 * @return 认证信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken token) {
		AuthenticationToken authenticationToken = (AuthenticationToken) token;
		String username = authenticationToken.getUsername();
		if (StringUtils.isEmpty(username) || authenticationToken.getPassword() == null)
			throw new IncorrectCredentialsException();
		String password = new String(authenticationToken.getPassword());
		String captchaId = authenticationToken.getCaptchaId();
		String captcha = authenticationToken.getCaptcha();
		String ip = authenticationToken.getHost();
		// 验证码
		if (org.apache.commons.lang3.ArrayUtils.contains(SettingUtils.get().getCaptchaTypes(), CaptchaType.salesmanLogin)) {
			if (!captchaService.isValid(CaptchaType.salesmanLogin, captchaId, captcha)) {
				throw new UnsupportedTokenException();
			}
		}
		Salesman salesman = service.findByUsername( username );
		if (salesman == null) {
			throw new UnknownAccountException();
		}
		if (!salesman.getIsEnabled()) {
			throw new DisabledAccountException();
		}
		Setting setting = SettingUtils.get();
		if (salesman.getIsLocked()) {
			if (ArrayUtils.contains(setting.getAccountLockTypes(), AccountLockType.salesman)) {
				int loginFailureLockTime = setting.getAccountLockTime();
				if (loginFailureLockTime == 0) {
					throw new LockedAccountException();
				}
				Date lockedDate = salesman.getLockedDate();
				Date unlockDate = DateUtils.addMinutes(lockedDate, loginFailureLockTime);
				if (new Date().after(unlockDate)) {
					salesman.setLoginFailureCount(0);
					salesman.setIsLocked(false);
					salesman.setLockedDate(null);
					service.update(salesman);
				} else {
					throw new LockedAccountException();
				}
			} else {
				salesman.setLoginFailureCount(0);
				salesman.setIsLocked(false);
				salesman.setLockedDate(null);
				service.update(salesman);
			}
		}
		if (!password.equalsIgnoreCase(salesman.getPassword())) {
			int loginFailureCount = salesman.getLoginFailureCount() + 1;
			if (loginFailureCount >= setting.getAccountLockCount()) {
				salesman.setIsLocked(true);
				salesman.setLockedDate(new Date());
			}
			salesman.setLoginFailureCount(loginFailureCount);
			service.update(salesman);
			throw new IncorrectCredentialsException();
		}

		// 更新登录信息
		salesman.setLoginIp(ip);
		salesman.setLoginDate(new Date());
		salesman.setLoginFailureCount(0);
		service.update(salesman);
		return new SimpleAuthenticationInfo(new Principal(AccountType.salesman, salesman.getId(), username), password, getName());
	}

	/**
	 * 获取授权信息(访问权限)
	 * 
	 * @param principals
	 *            principals
	 * @return 授权信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		return null;
	}

}